#include "TabControl.h"
#include <wx/dcbuffer.h>
#include "../gui/Icons.h"
#include "../events/TabChangedEvent.h"
#include <gtk/gtk.h>

namespace Impp
{

//*
BEGIN_EVENT_TABLE(TabControl, wxPanel)
	EVT_PAINT(TabControl::paintEvent)
	EVT_MOUSE_EVENTS(TabControl::onMouseDown)
	EVT_ERASE_BACKGROUND(TabControl::OnEraseBackground)
END_EVENT_TABLE()
//*/

TabControl::TabControl(wxWindow* parent, long id) :
	wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE), activeTab(0),maxOffset(0),offset(0)
{
	highlightTop = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
	highlightBottom = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
	highlightMiddle= highlightBottom;
	normalTop = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
	normalMiddle = normalTop;
	normalBottom = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW);
	
	bgTop = wxSystemSettings::GetColour(wxSYS_COLOUR_DESKTOP);
	bgMiddle = wxSystemSettings::GetColour(wxSYS_COLOUR_DESKTOP);
	bgBottom = wxSystemSettings::GetColour(wxSYS_COLOUR_DESKTOP);
	
	SetMaxSize(wxSize(10000, 32));
	SetMinSize(wxSize(100,32));
	
	addTab(new Tab(wxT("0"),Icons::getStatusIcon(ONLINE)));
	addTab(new Tab(wxT("1"),Icons::getStatusIcon(OFFLINE)));
	addTab(new Tab(wxT("2"),Icons::getStatusIcon(NA)));
	addTab(new Tab(wxT("3"),Icons::getStatusIcon(AWAY)));
	addTab(new Tab(wxT("4"),Icons::getStatusIcon(AWAY)));
	addTab(new Tab(wxT("5"),Icons::getStatusIcon(AWAY)));
	addTab(new Tab(wxT("6"),Icons::getStatusIcon(AWAY)));
	addTab(new Tab(wxT("7"),Icons::getStatusIcon(AWAY)));
	
}

TabControl::~TabControl()
{

}

void TabControl::addTab(Tab* tab){
	tabs.push_back(tab);
}

void TabControl::paintEvent(wxPaintEvent& evt){
    wxBufferedPaintDC dc(this);
    wxSize size = GetSize();
    


    
    //GtkWidget* win = (GtkWidget*) m_wxwindow;
    //GtkWidget* wid = (GtkWidget*) m_widget;
    /*
    gtk_paint_extension(m_widget->style, (GdkWindow*)m_wxwindow,
    		GTK_STATE_NORMAL, GTK_SHADOW_OUT,
			   0, m_widget, "tab",
			   0, 0,
			   100, 32,
			   GTK_POS_LEFT);
*/
    /*
    gtk_paint_box
    (
        m_wxwindow->style,
        m_wxwindow->widget,
        GTK_STATE_NORMAL,
        GTK_SHADOW_OUT,
        (GdkRectangle*) NULL,
        m_wxwindow,
        (char *)"button", // const_cast
        20,20,24,24
    );
 */
    
    wxFont systemFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
    dc.SetFont(systemFont);
    
    wxCoord spaceNormalTop =4;
    wxCoord border = 1;
    wxSize minTabSize(60,30);
    wxCoord innerSpaceX = 5;
    wxCoord rightLeftButtons = 10;
    
    wxFont f = dc.GetFont();
    f.SetPixelSize(wxSize(20,16));
    dc.SetFont(f);
    
    wxCoord hightHalf = minTabSize.y/2;
    wxRect r(0, 0, size.x, hightHalf);
    dc.GradientFillLinear(r, bgTop, bgMiddle, wxSOUTH);
    r = wxRect(0, hightHalf, size.x, hightHalf);
    dc.GradientFillLinear(r, bgMiddle, bgBottom, wxSOUTH);
    
    wxCoord width = (size.GetWidth())/tabs.size();
    
    size_t maxOffsetNew=0;
    
    while(width<minTabSize.x){
    	maxOffsetNew++;
    	width  = (size.GetWidth()-rightLeftButtons*2-1)/(tabs.size()-maxOffsetNew);
    }
    if(maxOffset!=maxOffsetNew){
        maxOffset=maxOffsetNew;
        if(activeTab<offset){
        	offset=activeTab-1;
        }else if(activeTab>=tabs.size()-maxOffset+offset){
        	offset=maxOffset;
        }
    }else{
        maxOffset=maxOffsetNew;
    }

    
    wxPoint pos(0,2);
    if(maxOffset>0){
    	pos.x+=rightLeftButtons;
    }
    
    if(offset>maxOffset){
    	offset=0;
    }
    
    wxCoord maxTitleSize = width - 3*innerSpaceX - 2*border- 16;
    
    for(size_t i = offset; i < tabs.size()-maxOffset+offset; i++){
    	wxString title = tabs[i]->getTitle();
    	wxBitmap* icon = tabs[i]->getIcon();
    	
        wxSize titleSize = dc.GetTextExtent(title);
        
        if(titleSize.x > maxTitleSize){
        	size_t trim = (maxTitleSize-20)/(titleSize.x/title.size());
        	if(trim > 0 && trim < title.size()){
        		title = title.SubString(0,trim) << wxT("...");
        		titleSize = dc.GetTextExtent(title);
        	}
        }
        
        
        tabs[i]->setSize(wxSize(width, titleSize.y));
        
        //activeTab
        if(i==activeTab){
            r = wxRect(pos.x, pos.y, width, minTabSize.y/2);
            dc.GradientFillLinear(r, highlightTop, highlightMiddle, wxSOUTH);
            r = wxRect(pos.x, pos.y+minTabSize.y/2, width, minTabSize.y/2);
            dc.GradientFillLinear(r, highlightMiddle, highlightBottom, wxSOUTH);
            
            dc.SetPen(*wxBLACK_PEN);
            //Left
            dc.DrawLine(wxPoint(pos.x,pos.y+2),wxPoint(pos.x,pos.y+minTabSize.y));
            //Right
            dc.DrawLine(wxPoint(pos.x+width,pos.y+2),wxPoint(pos.x+width,pos.y+minTabSize.y));
            //Top
            dc.DrawLine(wxPoint(pos.x+2,pos.y),wxPoint(pos.x+width-1,pos.y));
            //EdgeBg
            dc.SetBrush(wxBrush(bgTop,wxSOLID));
            dc.SetPen(wxPen(*wxBLACK,0,wxTRANSPARENT));
            dc.DrawRectangle(pos.x,pos.y,2,2);
            dc.DrawRectangle(pos.x+width-1,pos.y,2,2);
            //EdgePoint
            dc.SetBrush(*wxBLACK_BRUSH);
            dc.DrawRectangle(pos.x+1,pos.y+1,1,1);
            dc.DrawRectangle(pos.x+width-1,pos.y+1,1,1);
            //Text
            if(icon!=NULL){
            	dc.DrawBitmap(*icon,wxPoint(pos.x+border+innerSpaceX, (minTabSize.y-titleSize.y)/2+spaceNormalTop),true);
                dc.DrawText(title,wxPoint(pos.x+border+5+16+innerSpaceX,(minTabSize.y-titleSize.y)/2+spaceNormalTop));
            }else{
                dc.DrawText(title,wxPoint(pos.x+border+5,(minTabSize.y-titleSize.y)/2+spaceNormalTop));
            }

        }else{
        	//Normaler Tab
            r = wxRect(pos.x, pos.y+spaceNormalTop, width, minTabSize.y/2-spaceNormalTop);
            dc.GradientFillLinear(r, normalTop,  normalMiddle, wxSOUTH);
            r = wxRect(pos.x, pos.y+spaceNormalTop+minTabSize.y/2, width, minTabSize.y/2-spaceNormalTop);
            dc.GradientFillLinear(r,  normalMiddle,  normalBottom, wxSOUTH);
            dc.SetPen(*wxBLACK_PEN);
            //Left
            dc.DrawLine(wxPoint(pos.x,pos.y+spaceNormalTop),wxPoint(pos.x,pos.y+minTabSize.y));
            //Right
            dc.DrawLine(wxPoint(pos.x+width,pos.y+2+spaceNormalTop),wxPoint(pos.x+width,pos.y+minTabSize.y));
            //Top
            dc.DrawLine(wxPoint(pos.x,pos.y+spaceNormalTop),wxPoint(pos.x+width-1,pos.y+spaceNormalTop));
            //Bottom
            dc.DrawLine(wxPoint(pos.x,pos.y+minTabSize.y-1),wxPoint(pos.x+width,pos.y+minTabSize.y-1));
            //RightEdge
            dc.DrawRectangle(pos.x+width-1,pos.y+1+spaceNormalTop,1,1);
            //Text
            if(icon!=NULL){
            	dc.DrawBitmap(*icon,wxPoint(pos.x+border+innerSpaceX, (minTabSize.y-titleSize.y)/2+spaceNormalTop),true);
                dc.DrawText(title,wxPoint(pos.x+border+5+16+innerSpaceX,(minTabSize.y-titleSize.y)/2+spaceNormalTop));
            }else{
            	dc.DrawText(title,wxPoint(pos.x+border+5,(minTabSize.y-titleSize.y)/2+spaceNormalTop));
            }
            
        }
        
        pos.x+=width;
    }
    
    if(pos.x < size.x){
    	 dc.SetPen(*wxBLACK_PEN);
        //Bottom
        dc.DrawLine(wxPoint(pos.x,pos.y+minTabSize.y-1),wxPoint(pos.x+size.x,pos.y+minTabSize.y-1));
    }
    
    if(maxOffset>0){
    	dc.DrawBitmap(*Icons::tabLeft,wxPoint(0,0),true);
    	dc.DrawBitmap(*Icons::tabRight,wxPoint(size.x-10,0),true);
    }
    
}

void TabControl::onMouseDown(wxMouseEvent & event){
	size_t selectedTab = getTabByPos(event.GetPosition());
	wxCoord x = event.GetPosition().x;
	if(event.ButtonDown(wxMOUSE_BTN_LEFT)){
		if(selectedTab < tabs.size()){
			tabChanged(selectedTab);
			//wxLogDebug(wxT("Tab: %d"),selectedTab);
		}else if(x < 10){
			tabChanged(activeTab-1);
		}else if(x > GetSize().x-10){
			tabChanged(activeTab+1);
		}
	}else if(event.ButtonDown(wxMOUSE_BTN_MIDDLE)){
		if(selectedTab < tabs.size()){
			closeTab(selectedTab);
		}	
	}
	

}

size_t TabControl::getTabByPos(const wxPoint & pos){
   wxCoord x = 0;
   if(maxOffset>0){
	   x=10;
   }

   for(size_t i = offset; i < tabs.size()-maxOffset+offset; i++){
	   if(pos.x >= x && pos.x < x+tabs[i]->getSize().x){
		   return i;
	   }
	   x+=tabs[i]->getSize().x;
   }
   return 9999;
}

void TabControl::tabChanged(int tab){
	if(tab<0){
		tab=0;
	}else if (static_cast<size_t>(tab)>=tabs.size()){
		tab=tabs.size()-1;
	}
	if(static_cast<size_t>(tab)==activeTab){
		return;
	}
	
	Tab* oldTab = tabs[activeTab];
	Tab* newTab = tabs[tab];
	activeTab = tab;
	
	//wxLogDebug(wxT("offset: %d size: %d :maxOffset: %d"),offset,tabs.size(),maxOffset);
	
	if(static_cast<size_t>(tab)<offset){
		offset--;
	}else if(tab>=(int)offset+(int)tabs.size()-(int)maxOffset){
		offset++;
	}
	TabChangedEvent event(oldTab, newTab, EVT_TAB_CHANGED, GetId());
	
	AddPendingEvent(event);
	
	Refresh(false);
}

void TabControl::closeTab(size_t tab){
	if(tab<tabs.size()){
		Tab* t = tabs[tab];
		std::vector<Tab*>::iterator dIter(tabs.begin()); 
		for (; dIter != tabs.end(); ++dIter) { 
		      if(*dIter==t){
		    	  dIter = tabs.erase(dIter);
		    	  break;
		      }
		}
		delete t;
		
		if(tab==activeTab){
			if(activeTab>0){
				tabChanged(activeTab-1);
			}else{
				tabChanged(0);
			}
		}
		Refresh();
	}
}

void TabControl::OnEraseBackground(wxEraseEvent& event){}

}
